//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ShipmentDlg.h"
#include "FormUtilities.h"
#include "Calendar.h"
#include "StringUtilities.h"
#include "ShipmentDetailsDlg.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

const int CODE_SHIPMENT_NO = 1;
const int CODE_DATE        = 2;
const int CODE_AMOUNT      = 3;
const int CODE_PROVIDER    = 4;

//---------------------------------------------------------------------------

__fastcall TfrmShipmentDlg::TfrmShipmentDlg(TComponent* Owner, TDatabase* dbMain, TShipmentBridge* bridge, TShipment* shipment)
        : TForm(Owner)
{
   TFormUtilities::LocateForm(( TForm*)Owner, this);

   this->dbMain = dbMain;

   details = new TStringList();
   details->Duplicates = dupAccept;

   this->bridge  = bridge;
   this->shipment = shipment;
   lblCurrency->Caption = "(" + CurrencyString + ")";
   providerBridge = new TProviderBridge( dbMain);
   cmbProviders->Sorted = true;
   FillProvidersCombo();

   if ( shipment == NULL)
   {
      Caption = "Add new shipment";
      original = NULL;
   }
   else
   {
      Caption = "Update shipment";
      original = new TShipment( shipment);
      ShowShipment();
   }//if-else
}

void TfrmShipmentDlg :: FillProvidersCombo()
{
   providerBridge->GetProviders( cmbProviders->Items);
   if (cmbProviders->Items->Count > 0)
        cmbProviders->ItemIndex = 0;     
}

void TfrmShipmentDlg :: ShowShipment()
{
   edtNumber->Text = IntToStr( shipment->number);
   edtDate->Text   = DateToStr( shipment->shipmentDate);
   edtAmount->Text = FloatToStr( shipment->amount);

   int i = 0;
   bool found = false;

   while (( i < cmbProviders->Items->Count) && ( !found))
   {
      TProvider* provider = (TProvider*)cmbProviders->Items->Objects[ i];
      if ( provider->id == shipment->provider->id)
         found = true;
      else
         i++;     
   }

   if (found)
      cmbProviders->ItemIndex = i;
   else
      cmbProviders->ItemIndex = -1;  
}

void TfrmShipmentDlg :: GatherShipment()
{
   shipment->number       = StrToInt( edtNumber->Text);
   shipment->shipmentDate = StrToDate( edtDate->Text);
   shipment->amount       = edtAmount->Text;
   TProvider* provider = (TProvider*)cmbProviders->Items->Objects[ cmbProviders->ItemIndex];
   shipment->provider->id = provider->id;
}

void TfrmShipmentDlg :: AddNewShipment()
{
   bool doAdd;

   shipment = new TShipment();

   try
   {
      GatherShipment();

      if ( bridge->IsExist( shipment->number, shipment->shipmentDate))
         throw new TError( CODE_DATE, "Shipment already exists");

      bridge->Add( shipment);
   }
   __finally
   {
      delete shipment;
      shipment = NULL;
   }//try-finally
}

void TfrmShipmentDlg :: UpdateShipment()
{
   bool doUpdate;

   GatherShipment();

   if (( !original->IsEqual( shipment)) && ( bridge->IsExist( shipment->number, shipment->shipmentDate)))
      throw new TError( CODE_DATE, "Shipment already exists");

   bridge->Update( original, shipment);
}

void TfrmShipmentDlg :: ValidateData()
{
   if ( edtNumber->Text.Length() == 0)
      throw new TError( CODE_SHIPMENT_NO, "Shipment must be entered");

   try
   {
      StrToInt( edtNumber->Text);
   }
   catch( Exception * e)
   {
      throw new TError( CODE_SHIPMENT_NO, "Illegal shipment number");
   }//try-catch

   if ( edtDate->Text.Length() == 0)
      throw new TError( CODE_DATE, "Date must be entered");

   try
   {
      TDateUtilities::validate( edtDate->Text, "Illegal date");
   }
   catch( Exception * e)
   {
      throw new TError( CODE_DATE, e->Message);
   }//try-catch
   
   if ( edtAmount->Text.Length() == 0)
      throw new TError( CODE_AMOUNT, "Amount must be entered");

   try
   {
      StrToFloat( edtAmount->Text);
   }
   catch( Exception * e)
   {
      throw new TError( CODE_AMOUNT, "Illegal amount");
   }//try-catch

   if ( cmbProviders->ItemIndex == -1)
      throw new TError( CODE_PROVIDER, "Provider must be entered");
}

void TfrmShipmentDlg :: HandleError( TError * e)
{
   MessageDlg( e->Message,
               mtError,
               TMsgDlgButtons() << mbOK,
               0);

   switch ( e->GetCode())
   {
      case CODE_SHIPMENT_NO :
         edtNumber->SetFocus();
         break;

      case CODE_DATE :
         edtDate->SetFocus();
         break;
         
      case CODE_AMOUNT :
         edtAmount->SetFocus();
         break;

      case CODE_PROVIDER :
         cmbProviders->SetFocus();
         break;    
   }//switch

   ModalResult = mrNone;
}

//---------------------------------------------------------------------------

void __fastcall TfrmShipmentDlg::btnOKClick(TObject *Sender)
{
   try
   {
      ValidateData();
      
      if ( shipment == NULL)
         AddNewShipment();
      else
         UpdateShipment();

      for (int i = 0; i < details->Count; ++i)
      {
         TShipmentDetails* sd = (TShipmentDetails*)details->Objects[i];
         sd->shipmentNo = shipment->number;
      }

      bridge->UpdateDetails(shipment->number, details);
   }
   catch( TError * e)
   {
      HandleError( e);
   }//try-catch
}
//---------------------------------------------------------------------------


void __fastcall TfrmShipmentDlg::btnDateClick(TObject *Sender)
{
   TfrmCalendar * frmCalendar;

   frmCalendar = new TfrmCalendar( this);

   try
   {
      if ( edtDate->Text.Length() > 0)
         frmCalendar->calendar->Date = StrToDate( edtDate->Text);

      if ( frmCalendar->ShowModal() == mrOk)
         edtDate->Text = DateToStr( frmCalendar->calendar->Date);
   }
   __finally
   {
      delete frmCalendar;
   }
}
//---------------------------------------------------------------------------

void __fastcall TfrmShipmentDlg::FormDestroy(TObject *Sender)
{
   if ( original != NULL)
      delete original;

   TStringUtilites::Clear( cmbProviders->Items);   
   delete providerBridge;
}
//---------------------------------------------------------------------------

void __fastcall TfrmShipmentDlg::FormShow(TObject *Sender)
{
   grdDetails->Cells[ 0][ 0] = "FIRM";
   grdDetails->Cells[ 1][ 0] = "MODEL";
   grdDetails->Cells[ 2][ 0] = "AMOUNT";

   RefreshGrid(true);
}

void TfrmShipmentDlg::RefreshGrid(bool reload)
{
   TShipmentDetails* sd;
   int rowCount;
   int i;

   rowCount = 2;
   if (edtNumber->Text.Length() > 0 && reload)
      bridge->GetDetails( StrToInt64(edtNumber->Text), details);

   if ( details->Count > 1)
      rowCount = details->Count + 1;

   grdDetails->RowCount = rowCount;

   for ( i = 1; i < grdDetails->RowCount; i++)
      grdDetails->Rows[ i]->Clear();

   for ( i = 0; i < details->Count; i++)
   {
      sd = ( TShipmentDetails*)details->Objects[ i];

      grdDetails->Cells[ 0][ i + 1] = sd->firm;
      grdDetails->Cells[ 1][ i + 1] = sd->model;
      grdDetails->Cells[ 2][ i + 1] = sd->amount;
   }//for

   TFormUtilities::SetLastColumnWidth( grdDetails);

   SetButtonsState( grdDetails->Row);
}

void TfrmShipmentDlg::SetButtonsState( int row)
{
   bool enabled;

   enabled = ( details->Count > 0);
   
   btnDelete->Enabled = enabled;
}


//---------------------------------------------------------------------------

void __fastcall TfrmShipmentDlg::btnDeleteClick(TObject *Sender)
{
   TShipmentDetails* sd;

   sd = ( TShipmentDetails*)details->Objects[ grdDetails->Row - 1];

   if ( MessageDlg( "Are you sure ?",
                    mtWarning,
                    TMsgDlgButtons() << mbYes << mbNo,
                    0) == mrYes)
   {
        bridge->DeleteDetails( sd->id);
        delete sd;
        details->Delete( grdDetails->Row - 1);
        RefreshGrid(true);
   }
}
//---------------------------------------------------------------------------

void __fastcall TfrmShipmentDlg::btnAddClick(TObject *Sender)
{
   TfrmShipmentDetailsDlg * frmShipmentDetailsDlg;

   frmShipmentDetailsDlg = new TfrmShipmentDetailsDlg( this, dbMain, details);

   try
   {
      if ( frmShipmentDetailsDlg->ShowModal() == mrOk)
         RefreshGrid(false);
   }
   __finally
   {
      delete frmShipmentDetailsDlg;
   }
}
//---------------------------------------------------------------------------

